package com.kool.kmqtt.server.repository.redis;

import com.kool.kmqtt.util.SpringUtil;
import org.springframework.data.redis.core.*;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author luyu
 */
public class RedisClient {
    private final StringRedisTemplate stringRedisTemplate = SpringUtil.getBean(StringRedisTemplate.class);

    /**
     * 删除key
     *
     * @param key
     */
    public void delete(String key) {
        stringRedisTemplate.delete(key);
    }

    /**
     * 保存KV
     *
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    /**
     * 保存KV，自动过期删除，时间单位：秒
     *
     * @param key
     * @param value
     * @param timeout
     */
    public void set(String key, String value, long timeout) {
        stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    /**
     * 根据key 获取KV
     *
     * @param key
     * @return
     */
    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * 根据key前缀（不带“*”）获取KV
     *
     * @param keyPrefix
     * @return
     */
    public List<String> getKVByPrefix(String keyPrefix) {
        Set<String> keys = scan(keyPrefix + "*");
        if (keys != null) {
            List<String> values = new ArrayList<>();
            for (String key : keys) {
                String value = get(key);
                if (value != null) {
                    values.add(value);
                }
            }
            return values;
        }
        return null;
    }

    /**
     * 保存HASH
     *
     * @param hash
     * @param key
     * @param value
     */
    public void putHash(String hash, String key, String value) {
        stringRedisTemplate.opsForHash().put(hash, key, value);
    }

    /**
     * 获取HASH
     *
     * @param hash
     * @return
     */
    public Map<String, String> getHashMap(String hash) {
        HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
        return hashOperations.entries(hash);
    }

    /**
     * 获取HASH的KV的value列表
     *
     * @param hash
     * @return
     */
    public List<String> getHashValues(String hash) {
        HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
        return hashOperations.values(hash);
    }

    /**
     * 根据hash和key删除HASH的KV
     *
     * @param hash
     * @param key
     */
    public void deleteHashValue(String hash, String key) {
        HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
        hashOperations.delete(hash, key);
    }

    /**
     * scan方法获取key集合
     *
     * @param matchKey
     * @return
     */
    public Set<String> scan(String matchKey) {
        Set<String> keys = stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
            Set<String> keysTmp = new HashSet<>();
            Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(matchKey).count(1000).build());
            while (cursor.hasNext()) {
                keysTmp.add(new String(cursor.next()));
            }
            return keysTmp;
        });

        return keys;
    }

    /**
     * LIST增加元素
     *
     * @param key
     * @param value
     */
    public void addList(String key, String value) {
        //从右边插入
        stringRedisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * LIST进队列
     * 左进右出队列
     *
     * @param key
     * @param value
     */
    public void push(String key, String value) {
        stringRedisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * LIST出队列
     * 左进右出队列
     *
     * @param key
     */
    public String pop(String key) {
        return stringRedisTemplate.opsForList().rightPop(key);
    }

    /**
     * 根据key 获取LIST
     *
     * @param key
     * @return
     */
    public List<String> getList(String key) {
        Long size = stringRedisTemplate.opsForList().size(key);
        return stringRedisTemplate.opsForList().range(key, 0, size - 1);
    }

    /**
     * 根据key 删除LIST
     *
     * @param key
     */
    public void deleteList(String key) {
        stringRedisTemplate.delete(key);
    }


    /**
     * 自增1
     * KV结构
     *
     * @param key
     * @return
     */
    public void inrc(String key) {
        stringRedisTemplate.opsForValue().increment(key);
    }
}
